﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Collections;
using Titan.SqlTracer;
using System.Linq;
using System.Linq.Expressions;
using Titan.ExpressionAnalyse;

namespace Titan
{
    /// <summary>
    /// 数据库连接，实现IDbSession接口
    /// </summary>
    public class DbSession  : IDbSession 
    {

        #region sqlProvider实例缓存
        private static readonly Dictionary<Type, ISqlProvider> SqlProviders = new Dictionary<Type, ISqlProvider>();//缓存sqlProvider实例
        public static void RegisterTable(Type sqlProviderType, EntityType entityType, ITable table)
        {
            if (!SqlProviders.ContainsKey(sqlProviderType))
            {
                lock (SqlProviders)
                {
                    if (!SqlProviders.ContainsKey(sqlProviderType))
                    {
                        ISqlProvider sqlProviderNew = (ISqlProvider)Activator.CreateInstance(sqlProviderType);
                        SqlProviders.Add(sqlProviderType, sqlProviderNew);
                    }
                }
            }

            ISqlProvider sqlProvider = SqlProviders[sqlProviderType];
            sqlProvider.Tables.Add(entityType, table); 
        }
        /// <summary>
        /// 清除table,column,propertyAdapter缓存
        /// </summary>
        public static void ClearSchemaCache()
        {
            lock (SqlProviders)
            {
                foreach (ISqlProvider sqlProvider in SqlProviders.Values)
                {
                    sqlProvider.Tables.Clear();
                    sqlProvider.Statements.Clear();
                }
                SqlProviders.Clear();
                SqlAnalyzer.SqlAnalyseResults.Clear();
            }
        }
        #endregion


        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sqlProviderType">需要传入类型，考虑到动态生成DbSession，不能用泛型</param>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="sqlTracers">可以指定多个sql语句跟踪器，如果为null则不会有任何追踪</param>
        public DbSession(Type sqlProviderType,string connectionString, ISqlTracer[] sqlTracers)
        {
            if (!typeof(ISqlProvider).IsAssignableFrom(sqlProviderType))
            {
                throw new ArgumentException("sqlProviderType参数必须是实现ISqlProvider的类型", "sqlProviderType");
            }
            if (!SqlProviders.ContainsKey(sqlProviderType))
            {
                lock (SqlProviders)
                {
                    if (!SqlProviders.ContainsKey(sqlProviderType))
                    {
                        ISqlProvider sqlProvider = (ISqlProvider)Activator.CreateInstance(sqlProviderType);
                        SqlProviders.Add(sqlProviderType, sqlProvider);
                    }
                }
            }
            SqlProvider = SqlProviders[sqlProviderType];
            Connection = SqlProvider.CreateConnection();
            Connection.ConnectionString = connectionString;
            SqlTracers = sqlTracers;

        }
        /// <summary>
        /// 构造函数
        /// </summary> 
        /// <param name="connectionString">数据库连接字符串</param>
        public DbSession(Type sqlProviderType, string connectionString)
            : this(sqlProviderType, connectionString, null)
        {
        }
        /// <summary>
        /// 构造函数
        /// </summary>  
        public DbSession(Type sqlProviderType)
            : this(sqlProviderType, null, null)
        {
        }
        #endregion

        #region 接口属性
         

        public ISqlProvider SqlProvider { get; private set; } 

        public ISqlTracer[] SqlTracers { get; private set; } 

        public IDbConnection Connection { get; private set; } 


        public IDbTransaction Transaction { get; private set; }

        #endregion

        #region 接口方法
        
        public virtual void Open()
        {
            Connection.Open();
        }


        public virtual void Close()
        {
            Transaction = null;
            Connection.Close();
        }


        public virtual void BeginTransaction()
        {
            if (Connection == null) throw ExceptionFactory.ConnectionNotOpendException();
            if (Transaction != null) throw ExceptionFactory.TransactionOpendException();
            Transaction = Connection.BeginTransaction();
        }
        

        public virtual void BeginTransaction(IsolationLevel iso)
        {
            if (Connection == null) throw ExceptionFactory.ConnectionNotOpendException();
            if (Transaction != null) throw ExceptionFactory.TransactionOpendException();
            Transaction = Connection.BeginTransaction(iso);
        }


        

        public virtual void Commit()
        {
            if (Transaction == null) throw ExceptionFactory.TransactionNotOpendException();
            Transaction.Commit();
            Transaction = null;
        }
        

        public virtual void Rollback()
        {
            if (Transaction == null) throw ExceptionFactory.TransactionNotOpendException();
            Transaction.Rollback();
            Transaction = null;
        }
        #endregion

        #region 接口方法 常规helper
        

        public virtual DataRow ExecuteFirstDataRow(IDbCommand command)
        {
            DataRow dataRow = null;
            PrepareCommand(command);
            IDbDataAdapter ad = SqlProvider.CreateDataAdapter();
            ad.SelectCommand = command;
            var ad2 = ad as DbDataAdapter;
            var dt = new DataTable();
            ad2.Fill(0,1,dt);

            if (dt.Rows.Count > 0)
            {
                dataRow = dt.Rows[0];
            }

            return dataRow;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public virtual DataTable ExecuteDataTable(IDbCommand command)
        {
            PrepareCommand(command);
            IDbDataAdapter ad = SqlProvider.CreateDataAdapter();
            ad.SelectCommand = command;
            var ad2 = ad as DbDataAdapter;
            var dt = new DataTable();
            ad2.Fill(dt);

            return dt;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="pageSize"></param>
        /// <param name="pageIndex"></param>
        /// <returns></returns>
        public DataTable ExecuteDataTable(IDbCommand command, int pageSize, int pageIndex)
        {
            SqlProvider.WrapPaging(this,command, pageSize, pageIndex);
            return ExecuteDataTable(command);
        } 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="pageSize"></param>
        /// <param name="pageIndex"></param>
        /// <returns></returns>
        public IDataReader ExecuteReader(IDbCommand command, int pageSize, int pageIndex)
        {
            SqlProvider.WrapPaging(this,command, pageSize, pageIndex);
            return ExecuteReader(command);
        } 



        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual bool RecordExists(string sql)
        {
            IDbCommand command = Connection.CreateCommand();
            command.CommandText = sql;
            return RecordExists(command);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public virtual bool RecordExists(IDbCommand command)
        {
            PrepareCommand(command);
            object obj = command.ExecuteScalar();
            return obj != null;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual DataRow ExecuteFirstDataRow(string sql)
        {
            IDbCommand command = Connection.CreateCommand();
            command.CommandText = sql;
            return ExecuteFirstDataRow(command);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual DataTable ExecuteDataTable(string sql)
        {
            IDbCommand command = Connection.CreateCommand();
            command.CommandText = sql;
            return ExecuteDataTable(command);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual DataSet ExecuteDataSet(string sql)
        {
            IDbCommand command = Connection.CreateCommand();
            command.CommandText = sql;
            return ExecuteDataSet(command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public virtual DataSet ExecuteDataSet(IDbCommand command)
        {
            PrepareCommand(command);
            IDbDataAdapter ad = SqlProvider.CreateDataAdapter();
            ad.SelectCommand = command;
            var ds = new DataSet();
            ad.Fill(ds);
            return ds;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual IDataReader ExecuteReader(string sql)
        {
            IDbCommand command = Connection.CreateCommand();
            command.CommandText = sql;
            return ExecuteReader(command);
        } 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <param name="behavior"></param>
        /// <returns></returns>
        public virtual IDataReader ExecuteReader(IDbCommand command, CommandBehavior behavior)
        {
            PrepareCommand(command);
            return command.ExecuteReader(behavior);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public virtual IDataReader ExecuteReader(IDbCommand command)
        {
            PrepareCommand(command);
            return command.ExecuteReader();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual int ExecuteNonQuery(string sql)
        {
            IDbCommand command = Connection.CreateCommand();
            command.CommandText = sql;
            return ExecuteNonQuery(command);
        } 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public virtual int ExecuteNonQuery(IDbCommand command)
        {
            PrepareCommand(command);
            return command.ExecuteNonQuery();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual object ExecuteScalar(string sql)
        {
            IDbCommand command = Connection.CreateCommand();
            command.CommandText = sql;
            return ExecuteScalar(command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public virtual object ExecuteScalar(IDbCommand command)
        {
            PrepareCommand(command);
            return command.ExecuteScalar();
        }
        #endregion




        #region 接口方法 ORM对象操作

        public T ConvertDatabaseValue<T>(object databaseValue)
        {
            return (T)SqlProvider.ConvertDbValue(databaseValue, typeof (T));
        }


        #region Insert
        public int Insert(object obj)
        {
            return Insert(null, obj,null);
        }
        public int Insert(object obj, IEnumerable<string> excludePropertyNames)
        {
            return Insert(null, obj, excludePropertyNames);
        } 
        public int Insert(object obj, params string[] excludePropertyNames)
        {
            return Insert(null, obj, (IEnumerable<string>)excludePropertyNames);
        }
        public int Insert(object obj, IEnumerable<IPropertyExpression> excludePropertys)
        {
            List<string> excludePropertyNames = new List<string>();
            foreach (IPropertyExpression property in excludePropertys)
            {
                excludePropertyNames.Add(property.PropertyName);
            }
            return Insert(null, obj, excludePropertyNames);
        }
        public int Insert(object obj, params IPropertyExpression[] excludePropertys)
        {
            return Insert(obj, (IEnumerable<IPropertyExpression>)excludePropertys);
        }

        //public int Insert(IDictionary<string, string> tableMapping, object obj)
        //{
        //    return InsertExclude(tableMapping, obj, null);
        //}
        //public int Insert(IDictionary<string, string> tableMapping, object obj, params string[] excludePropertyNames)
        //{
        //    return InsertExclude(tableMapping, obj, (IEnumerable<string>)excludePropertyNames);
        //}

        public int Insert(IDictionary<string, string> tableMapping, object obj, IEnumerable<string> excludePropertyNames )
        {
            return InsertExclude(tableMapping, obj, excludePropertyNames);
        } 
        private int InsertExclude(IDictionary<string, string> tableMapping, object obj, IEnumerable<string> excludePropertyNames)
        {
            if (obj == null) throw ExceptionFactory.EntityNullException("obj");

            EntityType entityType = new EntityType(obj);
            ITable table = SqlProvider.GetTableByEntityType(entityType);
            IEnumerable<string> insertPropertyNames = excludePropertyNames == null ? table.InsertProperties : table.InsertProperties.Except(excludePropertyNames, StringComparer.OrdinalIgnoreCase);

            NameValueExpressionCollection nameValues = new NameValueExpressionCollection();
            foreach (string property in insertPropertyNames)
            {
                IColumn column = table.Columns[property];
                nameValues.Add(property, column.PropertyAdapter.GetValue(obj));
            }
            return SqlProvider.Insert(this, tableMapping, entityType, nameValues, obj);
        }
        #endregion

        #region Update
        public int Update(object obj)
        {
            EntityType entityType = new EntityType(obj);
            ITable table = SqlProvider.GetTableByEntityType(entityType);
            return Update(null, obj, table.NonPrimaryKeyProperties);
        }
        public int Update(object obj, IEnumerable<string> updatePropertyNames)
        {
            return Update(null, obj, updatePropertyNames);
        } 
        public int Update(object obj, params string[] updatePropertyNames)
        {
            return Update(null, obj, (IEnumerable<string>)updatePropertyNames);
        }
        public int Update(object obj, params IPropertyExpression[] updatePropertys)
        {
            return Update(obj, (IEnumerable<IPropertyExpression>)updatePropertys);
        }
        public int Update(object obj, IEnumerable<IPropertyExpression> updatePropertys)
        {
            List<string> updatePropertyNames = new List<string>();
            foreach (IPropertyExpression property in updatePropertys)
            {
                updatePropertyNames.Add(property.PropertyName);
            }
            return Update(null, obj, updatePropertyNames);
        }

        //public int Update(IDictionary<string, string> tableMapping, object obj)
        //{
        //    if (obj == null) throw ExceptionFactory.EntityNullException("obj");
        //    EntityType entityType = new EntityType(obj);
        //    ITable table = SqlProvider.GetTableByEntityType(entityType);
        //    return Update(tableMapping, obj, table.NonPrimaryKeyProperties);
        //}


        public int Update(IDictionary<string, string> tableMapping, object obj, IEnumerable<string> updatePropertyNames)
        {
            if (obj == null) throw ExceptionFactory.EntityNullException("obj");

            UpdateExpression updateExpression = new UpdateExpression(); 
            updateExpression.Wheres = CreateConditionByKeyColumn(obj);

            EntityType entityType = new EntityType(obj);
            ITable table = SqlProvider.GetTableByEntityType(entityType);
            IEnumerable<string> updates = updatePropertyNames == null ? table.NonPrimaryKeyProperties : updatePropertyNames;//如果传入null则更新全部字段
            foreach (string update in updates)
            {
                IColumn column = table.Columns[update];
                updateExpression.Updates.Add(update, column.PropertyAdapter.GetValue(obj));
            }
             
            return SqlProvider.Update(this, tableMapping, entityType, updateExpression);
        }
        //public int Update(IDictionary<string, string> tableMapping, object obj, params string[] updatePropertyNames)
        //{
        //    return Update(tableMapping, obj, (IEnumerable<string>)updatePropertyNames);
        //} 
        #endregion

        #region Delete
        public int Delete(object obj)
        {
            return Delete(null, obj);
        }

        public int Delete(IDictionary<string, string> tableMapping, object obj)
        {
            ConditionCollection conditionCollection = CreateConditionByKeyColumn(obj);

            EntityType entityType = new EntityType(obj);
            return SqlProvider.Delete(this, tableMapping, entityType, conditionCollection);
        }
        #endregion

        #region BatchUpdate
        public int BatchUpdate(object obj, IConditionExpression conditionExpression, IEnumerable<string> updatePropertyNames)
        {
            return BatchUpdate(null, obj, conditionExpression, updatePropertyNames);
        } 
        public int BatchUpdate(object obj, IConditionExpression conditionExpression, params string[] updatePropertyNames)
        {
            return BatchUpdate(null, obj, conditionExpression, (IEnumerable<string>)updatePropertyNames);
        }

        public int BatchUpdate(IDictionary<string, string> tableMapping, object obj, IConditionExpression conditionExpression, IEnumerable<string> updatePropertyNames)
        {
            if (obj == null) throw ExceptionFactory.EntityNullException("obj");

            IUpdateExpression updateExpression = new UpdateExpression();
            updateExpression.Wheres = Util.ToConditionCollection(conditionExpression);

            EntityType entityType = new EntityType(obj);
            ITable table = SqlProvider.GetTableByEntityType(entityType);
            IEnumerable<string> updates = updatePropertyNames == null ? table.NonPrimaryKeyProperties : updatePropertyNames;//如果传入null则更新全部字段 
            foreach (string update in updates)
            {
                IColumn column = table.Columns[update];
                updateExpression.Updates.Add(new NameValueExpression(update, column.PropertyAdapter.GetValue(obj)));
            }

            return SqlProvider.Update(this, tableMapping, entityType, updateExpression);
        }

        public int BatchUpdate(IDictionary<string, string> tableMapping, object obj, IConditionExpression conditionExpression, params string[] updatePropertyNames)
        {
            return BatchUpdate(tableMapping, obj, conditionExpression, (IEnumerable<string>)updatePropertyNames); 
        } 
        #endregion

        #region BatchDelete
        public int BatchDelete<T>(IConditionExpression conditionExpression)
        {
            return BatchDelete<T>(null, conditionExpression);
        }
        public int BatchDelete(Type entityType,IConditionExpression conditionExpression)
        {
            return BatchDelete(null, entityType,conditionExpression);
        }
        public int BatchDelete(EntityType entityType, IConditionExpression conditionExpression)
        {
            return BatchDelete(null, entityType,conditionExpression);
        }
        public int BatchDelete<T>(Expression<Func<T, bool>> expression)
        {
            return BatchDelete<T>(null, expression);
        }
        public int BatchDelete<T>(IDictionary<string, string> tableMapping, IConditionExpression conditionExpression)
        {

            EntityType entityType = new EntityType(typeof(T));
            return SqlProvider.Delete(this, tableMapping, entityType, Util.ToConditionCollection(conditionExpression));
        }
        public int BatchDelete(IDictionary<string, string> tableMapping, EntityType entityType, IConditionExpression conditionExpression)
        {
            return SqlProvider.Delete(this, tableMapping, entityType, Util.ToConditionCollection(conditionExpression));
        }
        public int BatchDelete(IDictionary<string, string> tableMapping, Type entityType, IConditionExpression conditionExpression)
        {
            return SqlProvider.Delete(this, tableMapping, new EntityType(entityType), Util.ToConditionCollection(conditionExpression));
        }

        public int BatchDelete<T>(IDictionary<string, string> tableMapping, Expression<Func<T, bool>> expression)
        {
            ConditionCollection<T> cs = new ConditionCollection<T>(expression);
            return BatchDelete<T>(tableMapping, cs);
        }
        #endregion

        #region Select
        public bool Select(object obj)
        {
            EntityType entityType = new EntityType(obj);
            ITable table = SqlProvider.GetTableByEntityType(entityType);
            return Select(null, obj, table.NonPrimaryKeyProperties);
        }

        public bool Select(object obj, IEnumerable<string> outputPropertyNames)
        {
            return Select(null, obj, outputPropertyNames);
        }

        public bool Select(object obj, params string[] outputPropertyNames)
        {
            return Select(null, obj, (IEnumerable<string>)outputPropertyNames);
        }

        public bool Select(object obj, IEnumerable<IPropertyExpression> outputPropertys)
        {
            List<string> outputPropertyNames = new List<string>();
            foreach (IPropertyExpression property in outputPropertys)
            {
                outputPropertyNames.Add(property.PropertyName);
            }
            return Select(null, obj, outputPropertyNames);
        }

        public bool Select(object obj, params IPropertyExpression[] outputPropertys)
        {
            return Select(obj, (IEnumerable<IPropertyExpression>)outputPropertys);
        } 

        //public bool Select(IDictionary<string, string> tableMapping, object obj)
        //{
        //    if (obj == null) throw ExceptionFactory.EntityNullException("obj");

        //    EntityType entityType = new EntityType(obj);
        //    ITable table = SqlProvider.GetTableByEntityType(entityType);
        //    return Select(tableMapping, obj, table.NonPrimaryKeyProperties);
        //}

        public bool Select(IDictionary<string, string> tableMapping, object obj, IEnumerable<string> outputPropertyNames)
        {
            QueryExpression queryExpression = new QueryExpression();
            queryExpression.Selects.Add(outputPropertyNames);
            queryExpression.Wheres = CreateConditionByKeyColumn(obj);

            var listType = typeof(List<>).MakeGenericType(obj.GetType());
            var list = (IList)Activator.CreateInstance(listType);
            list.Add(obj);


            EntityType entityType = new EntityType(obj);
            var matchedCount = SqlProvider.SelectCollection(this, tableMapping, entityType, list, queryExpression, false);


            return matchedCount >= 1;
        } 
        //public bool Select(IDictionary<string, string> tableMapping, object obj, params string[] updatePropertyNames)
        //{
        //    return Select(tableMapping, obj, (IEnumerable<string>)updatePropertyNames);
        //} 
        #endregion

        #region SelectCollection
        public int SelectCollection<T>(IList<T> list, IQueryExpression queryExpression)
        {
            return SelectCollection<T>(null, list, queryExpression);
        }
        public int SelectCollection(Type entityType, IList list, IQueryExpression queryExpression)
        {
            return SelectCollection(null,entityType, list, queryExpression);
        }
        public int SelectCollection(EntityType entityType, IList list, IQueryExpression queryExpression)
        {
            return SelectCollection(null, entityType,list, queryExpression);
        }

        public int SelectCollection<T>(IDictionary<string, string> tableMapping, IList<T> list, IQueryExpression queryExpression)
        {

            EntityType entityType = new EntityType(typeof(T));
            return SqlProvider.SelectCollection(this, tableMapping, entityType, (IList)list, queryExpression, true);
        }
        public int SelectCollection(IDictionary<string, string> tableMapping, Type entityType, IList list, IQueryExpression queryExpression)
        {
            EntityType entityType2 = new EntityType(entityType);
            return SqlProvider.SelectCollection(this, tableMapping, entityType2, list, queryExpression, true);
        }
        public int SelectCollection(IDictionary<string, string> tableMapping, EntityType entityType, IList list, IQueryExpression queryExpression)
        {
            EntityType entityType2 = new EntityType(entityType);
            return SqlProvider.SelectCollection(this, tableMapping, entityType2, list, queryExpression, true);
        }
        public int SelectCount<T>(IConditionExpression conditionExpression)
        {
            return SelectCount<T>(null, conditionExpression);
        }
        public int SelectCount(Type entityType,IConditionExpression conditionExpression)
        {
            return SelectCount(null, entityType,conditionExpression);
        }
        public int SelectCount(EntityType entityType, IConditionExpression conditionExpression)
        {
            return SelectCount(null, entityType,conditionExpression);
        }
        public int SelectCount<T>(Expression<Func<T, bool>> expression)
        {
            return SelectCount<T>(null,  expression);
        }

        public int SelectCount<T>(IDictionary<string, string> tableMapping, IConditionExpression conditionExpression)
        { 
            EntityType entityType = new EntityType(typeof(T));
            return SqlProvider.SelectCount(this, tableMapping, entityType, Util.ToConditionCollection(conditionExpression));
        }
        public int SelectCount(IDictionary<string, string> tableMapping, Type entityType, IConditionExpression conditionExpression)
        { 
            return SqlProvider.SelectCount(this, tableMapping, new EntityType(entityType), Util.ToConditionCollection(conditionExpression));
        }
        public int SelectCount(IDictionary<string, string> tableMapping, EntityType entityType, IConditionExpression conditionExpression)
        { 
            return SqlProvider.SelectCount(this, tableMapping, entityType, Util.ToConditionCollection(conditionExpression));
        }
        public int SelectCount<T>(IDictionary<string, string> tableMapping, Expression<Func<T, bool>> expression)
        {
            ConditionCollection<T> cs = new ConditionCollection<T>(expression);
            return SelectCount<T>(tableMapping, cs);
        }

        #endregion

        #region Exists


        public bool Exists(Type entityType, IConditionExpression conditionExpression)
        {
            return Exists(null, new EntityType(entityType), conditionExpression);
        }
        public bool Exists(EntityType entityType, IConditionExpression conditionExpression)
        {
            return Exists(null, entityType, conditionExpression);
        }
        public bool Exists(IDictionary<string, string> tableMapping, Type entityType, IConditionExpression conditionExpression)
        {
            return Exists(tableMapping, new EntityType(entityType), conditionExpression);
        }
        public bool Exists(IDictionary<string, string> tableMapping, EntityType entityType, IConditionExpression conditionExpression)
        {
            return SqlProvider.Exists(this, tableMapping, entityType, Util.ToConditionCollection(conditionExpression));
        }



        public bool Exists(object obj)
        {
            return Exists(null, obj);
        }


        public bool Exists(IDictionary<string, string> tableMapping, object obj)
        {
            ConditionCollection conditionCollection = CreateConditionByKeyColumn(obj);


            EntityType entityType = new EntityType(obj);
            return SqlProvider.Exists(this, tableMapping, entityType, Util.ToConditionCollection(conditionCollection));
        }


        public bool Exists<T>(IConditionExpression conditionExpression)
        {
            return Exists<T>(null, conditionExpression);
        }
        public bool Exists<T>(Expression<Func<T, bool>> expression)
        {
            return Exists<T>(null, expression);
        }


        public bool Exists<T>(IDictionary<string, string> tableMapping, IConditionExpression conditionExpression)
        {

            EntityType entityType = new EntityType(typeof(T));
            return SqlProvider.Exists(this, tableMapping, entityType, Util.ToConditionCollection(conditionExpression));
        }
        public bool Exists<T>(IDictionary<string, string> tableMapping, Expression<Func<T, bool>> expression)
        {
            ConditionCollection<T> cs = new ConditionCollection<T>(expression);
            return Exists<T>(tableMapping, cs);
        }

        #endregion

        public void ExecuteReaderAndFill(object obj, IList[] lists) {
            this.ExecuteReaderAndFill( obj, lists,null);
        }

        public void ExecuteReaderAndFill(object obj, IList[] lists, EntityType[] entityTypes)
        {
            if (obj == null) throw ExceptionFactory.EntityNullException("obj");
            int i = 0;
            foreach (IList list in lists)
            {
                if (list == null) throw ExceptionFactory.EntityNullException("lists[" + i + "]");
                if (!list.GetType().IsGenericType)
                {
                    throw new ArgumentException("必须是泛型接口");
                }
                i++;
            }
            SqlProvider.ExecuteReaderAndFill(this, obj, lists, entityTypes);
        }
        public IDataReader ExecuteReader(object obj)
        {
            if (obj == null) throw ExceptionFactory.EntityNullException("obj");
            return SqlProvider.ExecuteReader(this, obj);
        }
        public int ExecuteNonQuery(object obj)
        {
            if (obj == null) throw ExceptionFactory.EntityNullException("obj");
            return SqlProvider.ExecuteNonQuery(this, obj); 
        } 

        #endregion

        public void Dispose()
        {
            Close();
        }
        
        

        
        private ConditionCollection CreateConditionByKeyColumn(object obj)
        {
            if (obj == null) throw ExceptionFactory.EntityNullException("obj");
            var conditionExpressions = new ConditionCollection();


            EntityType entityType = new EntityType(obj);
            var table = SqlProvider.GetTableByEntityType(entityType);
            foreach (var column in table.PrimaryKeyColumns)
            {
                conditionExpressions.Add(new ConditionItem(column.PropertyAdapter.PropertyName, ConditionOperator.Equal, column.PropertyAdapter.GetValue(obj)));
            }
            return conditionExpressions;
        }


        private void PrepareCommand(IDbCommand command)
        {
            if (command.Connection == null)
            {
                if (Connection == null) throw ExceptionFactory.ConnectionNotOpendException();
                command.Connection = Connection;
            }
            if (command.Transaction == null)
            {
                if (Transaction != null && Transaction.Connection != null)
                {
                    command.Transaction = Transaction;
                }
            }

            //trace sql
            if (SqlTracers == null) return;
            foreach (ISqlTracer sqlTracer in SqlTracers)
            {
                sqlTracer.Trace(command);
            }
        }
    }
}
